package com.ctrip.framework.apollo.biz.utils;

import com.ctrip.framework.apollo.biz.entity.Item;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.springframework.beans.BeanUtils;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;


public class ConfigChangeContentBuilder {

  private static final Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();

  /**
   * 创建 Item 集合
   */
  private List<Item> createItems = new LinkedList<>();
  /**
   * 更新 Item 集合
   */
  private List<ItemPair> updateItems = new LinkedList<>();
  /**
   * 删除 Item 集合
   */
  private List<Item> deleteItems = new LinkedList<>();


  public ConfigChangeContentBuilder createItem(Item item) {
    if (!StringUtils.isEmpty(item.getKey())){
      createItems.add(cloneItem(item));
    }
    return this;
  }

  public ConfigChangeContentBuilder updateItem(Item oldItem, Item newItem) {
    if (!oldItem.getValue().equals(newItem.getValue())){
      ItemPair itemPair = new ItemPair(cloneItem(oldItem), cloneItem(newItem));
      updateItems.add(itemPair);
    }
    return this;
  }

  public ConfigChangeContentBuilder deleteItem(Item item) {
    if (!StringUtils.isEmpty(item.getKey())) {
      deleteItems.add(cloneItem(item));
    }
    return this;
  }

  /**
   * 判断是否有变化。当且仅当有变化才记录 Commit
   */
  public boolean hasContent(){
    return !createItems.isEmpty() || !updateItems.isEmpty() || !deleteItems.isEmpty();
  }

  public String build() {
    //因为事务第一段提交并没有更新时间,所以build时统一更新
    Date now = new Date();

    for (Item item : createItems) {
      item.setDataChangeLastModifiedTime(now);
    }

    for (ItemPair item : updateItems) {
      item.newItem.setDataChangeLastModifiedTime(now);
    }

    for (Item item : deleteItems) {
      item.setDataChangeLastModifiedTime(now);
    }
    // JSON 格式化成字符串
    return gson.toJson(this);
  }

  static class ItemPair {

    //老
    Item oldItem;
    //新
    Item newItem;

    public ItemPair(Item oldItem, Item newItem) {
      this.oldItem = oldItem;
      this.newItem = newItem;
    }
  }

  Item cloneItem(Item source) {
    Item target = new Item();

    BeanUtils.copyProperties(source, target);

    return target;
  }

  public static ConfigChangeContentBuilder convertJsonString(String content) {
    return gson.fromJson(content, ConfigChangeContentBuilder.class);
  }

  public List<Item> getCreateItems() {
    return createItems;
  }

  public List<ItemPair> getUpdateItems() {
    return updateItems;
  }

  public List<Item> getDeleteItems() {
    return deleteItems;
  }
  /**
   * // 已经使用 http://tool.oschina.net/codeformat/json/ 进行格式化，实际是**紧凑型**
   * {
   *     "createItems": [ ],
   *     "updateItems": [
   *         {
   *             "oldItem": {
   *                 "namespaceId": 32,
   *                 "key": "key4",
   *                 "value": "value4123",
   *                 "comment": "123",
   *                 "lineNum": 4,
   *                 "id": 15,
   *                 "isDeleted": false,
   *                 "dataChangeCreatedBy": "apollo",
   *                 "dataChangeCreatedTime": "2018-04-27 16:49:59",
   *                 "dataChangeLastModifiedBy": "apollo",
   *                 "dataChangeLastModifiedTime": "2018-04-27 22:37:52"
   *             },
   *             "newItem": {
   *                 "namespaceId": 32,
   *                 "key": "key4",
   *                 "value": "value41234",
   *                 "comment": "123",
   *                 "lineNum": 4,
   *                 "id": 15,
   *                 "isDeleted": false,
   *                 "dataChangeCreatedBy": "apollo",
   *                 "dataChangeCreatedTime": "2018-04-27 16:49:59",
   *                 "dataChangeLastModifiedBy": "apollo",
   *                 "dataChangeLastModifiedTime": "2018-04-27 22:38:58"
   *             }
   *         }
   *     ],
   *     "deleteItems": [ ]
   * }
   */
}
